/**
 * This base class is implemented as an integer representation for the 20 bit
 * binary word. These 20 bit words are the instructions for the Machine.
 * 
 * @author Seth Mielke, Jonathan Hsu
 * 
 * @modified 8/6/11
 * 
 */
public class Word implements WordInterface {
	private int value;

	Word() {
		this.value = 0;
	}

	Word(int value) {
		this();
		checkValue(value);
	}

	public int get() {
		return this.value;
	}

	public void set(int value) {
		checkValue(value);
	}

	/**
	 * @return integer representation of the 4 bit op field
	 */
	public int op() {
		return this.value >> 16 & 0x0000000F;
	}

	/**
	 * @return integer representation of the 2 bit u2 field
	 */
	public int u2() {
		return this.value >> 14 & 0x00000003;
	}

	/**
	 * @return integer representation of the 2 bit r field
	 */
	public int r() {
        return this.value >> 12 & 0x00000003;
	}

	/**
	 * @return integer representation of the 2 bit x field
	 */
	public int x() {
		return this.value >> 10 & 0x00000003;
	}

	/**
	 * @return integer representation of the 2 bit u1 field
	 */
	public int u1() {
		return this.value >> 8 & 0x00000003;
	}

	/**
	 * @return integer representation of the 8 bit s field
	 */
	public int s() {
		return this.value & 0x000000FF;
	}

    /**
     * @return 5 character hexadecimal representation of the word
     */
    public String toString() {
        return String.format("%08x", this.value).substring(3).toUpperCase();
    }

    /**
     * @return deep copy of Word
     */
    public Word copy() {
        return new Word(this.value);
    }

	// Error check to see if value is out of range, this is done on both
	// instantiation and value setting.
	private void checkValue(int value) {
		if (value > 524287) { // 524,287 = 2^19 - 1
			// this.value = 0;
			System.out.println(value + " is too Big");
		} else if (value < -524288) { // -524,288 = -2^19
			// this.value = 0;
			System.out.println(value + " is too small");
		} else {
			this.value = value;
		}
	}
}
